/**
 * Create in 2012-4-18.
 */
package kit4j.ui.cs.awt;

import java.awt.Component;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.lang.reflect.InvocationTargetException;

/**
 * 组件分步移动操作实现类。
 * 
 * @author MiniKnife
 * 
 */
public class DynamicComponentStepMover extends AbstractDynamicComponentStepOperator {

	/**
	 * 绑定的需要移动的组件对象。
	 */
	private Component component;

	/**
	 * 当前移动到的位置。
	 */
	private Point2D currentLocation;

	/**
	 * 下一个将要移动到的位置。
	 */
	private Point nextLocation;

	/**
	 * 组件对象移动的起始位置。
	 */
	private Point2D startLocation;
	
	/**
	 * 组件对象移动的目标终点位置。
	 */
	private Point2D targetLocation;

	/**
	 * 移动的坐标增量。
	 */
	private Point2D locationIncrement;

	/**
	 * 创建一个组件移动操作者对象。
	 * 
	 * @param component
	 *            要移动的组件对象
	 * @param startLocation
	 *            移动的起始位置
	 * @param targetLocation
	 *            移动的目标终点位置
	 * @param locationIncrement
	 *            移动的坐标增量
	 * @throws IllegalArgumentException
	 *             如果{@code locationIncrement.getX()}和{@code locationIncrement.getY()}返回值都为0，则抛出此异常。
	 */
	public DynamicComponentStepMover(Component component, Point2D startLocation, Point2D targetLocation,
			Point2D locationIncrement) throws IllegalArgumentException {
		super((long) (Math.abs(targetLocation.getX() - startLocation.getX()) + Math.abs(targetLocation.getY()
				- startLocation.getY())));

		checkLocationIncrement(locationIncrement);

		this.component = component;
		this.nextLocation = clonePoint(startLocation);
		this.currentLocation = clonePoint(startLocation);
		this.startLocation = clonePoint(startLocation);
		this.targetLocation = clonePoint(targetLocation);
		this.locationIncrement = clonePoint(locationIncrement);
	}

	/**
	 * 验证移动的坐标增量是否合法。
	 * 
	 * @param locationIncrement
	 *            移动的坐标增量
	 * @throws IllegalArgumentException
	 *             如果{@code locationIncrement.getX()}和{@code locationIncrement.getY()}返回值都为0，则抛出此异常。
	 */
	private void checkLocationIncrement(Point2D locationIncrement) throws IllegalArgumentException {
		if (locationIncrement.getX() == 0 && locationIncrement.getY() == 0) {
			throw new IllegalArgumentException("locationIncrement.getX()==0, locationIncrement.getY()==0");
		}
	}

	/**
	 * 从指定Point对象复制创建一个具有相同位置的点。
	 * 
	 * @param p
	 *            点
	 * @return 复制创建的点
	 */
	private Point clonePoint(Point2D p) {
		Point clone = new Point();

		clone.setLocation(p);

		return clone;
	}

	/**
	 * @see kit4j.common.task.StepTask.StepTaskCallback#execute()
	 */
	@Override
	public void execute() {
		try {
			invokeAndWait(new Runnable() {

				@Override
				public void run() {
					component.setLocation(nextLocation);

					currentLocation.setLocation(nextLocation);
					nextLocation.setLocation(nextLocation.getX() + locationIncrement.getX(), nextLocation.getY()
							+ locationIncrement.getY());
					
					if(startLocation.getX() > targetLocation.getX() && nextLocation.getX() < targetLocation.getX() || 
							startLocation.getX() < targetLocation.getX() && nextLocation.getX() > targetLocation.getX()) {
						nextLocation.setLocation(targetLocation.getX(), nextLocation.getY());
					}
					if(startLocation.getY() > targetLocation.getY() && nextLocation.getY() < targetLocation.getY() || 
							startLocation.getY() < targetLocation.getY() && nextLocation.getY() > targetLocation.getY()) {
						nextLocation.setLocation(nextLocation.getX(), targetLocation.getY());
					}
				}

			});
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @see kit4j.common.task.StepTask.StepTaskCallback#getCurrentTaskProgressRate()
	 */
	@Override
	public long getCurrentTaskProgressRate() {
		return (long) (Math.abs(currentLocation.getX() - startLocation.getX()) + Math.abs(currentLocation.getY()
				- startLocation.getY()));
	}

}
